; Lab3 - catchLED.asm
; Ben Gentry
; 10/1/12

#include <p16F887.inc>
	__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

     cblock     0x20
Delay			 ; delay registers
Delay1           
Delay2
Display          ; define a variable to hold the diplay
ButtonHeld		 ; flag for switch being held down
     endc

; setup program I/O and flags   
     org 0
Start:
     bsf       STATUS,RP0     ; select Register Bank 1
     movlw     0xFF
     movwf     TRISA          ; make PortA all input
     clrf      TRISD          ; make PortD all output
     movlw     0x01     
     movwf     TRISB          ; make RBO pin input (switch)
	 movlw     0x00           ; Left Justified, Vdd-Vss referenced
     movwf     ADCON1
     bsf       STATUS,RP1     ; select Register Bank 3
     movlw     0x1F           ; we want all Port A pins Analoga
     movwf     ANSEL
	 movlw 	   0x00
	 movwf	   ANSELH		  ; PortB pins are digitial (important as RB0 is switch)	
     bcf       STATUS,RP0     ; back to Register Bank 0
     bcf       STATUS,RP1 
     movlw     0x41
     movwf     ADCON0         ; configure A2D for Fosc/8, Channel 0 (RA0), and turn on the A2D module
     movlw     0x80
     movwf     Display
	 movlw     0
     movwf     ButtonHeld     ; assume switch is up

; display LEDs, execute A2D conversion, and watch the switch
MainLoop:
     movf      Display,w           ; copy the display to the LEDs
     movwf     PORTD
     nop                           ; wait 5uS for A2D amp to settle and capacitor to charge.
     nop                           ; wait 1uS
     nop                           ; wait 1uS
     nop                           ; wait 1uS
     nop                           ; wait 1uS
     bsf       ADCON0,GO_DONE      ; start conversion
     btfss     ADCON0,GO_DONE      ; this bit will change to zero when the conversion is complete
     goto      $-1
     movf      ADRESH,w            ; copy the display to the LEDs
     addlw     1					
     movwf     Delay2			   ; adjust LED delay time based on potentiometer
     btfss	   PORTB, 0			   ; check if the switch is pressed
     call      Debounce			   ; if yes, call Debounce
	 bcf	   ButtonHeld, 0	   ; set switch flag to 0
	 btfss	   PORTB, 0			   ; check if switch is depressed
	 bsf	   ButtonHeld, 0	   ; if yes, set switch flag

; A2D conversion delay
A2DDelayLoop:
     decfsz    Delay1,f            ; Waste time.  
     goto      A2DDelayLoop        ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions
     decfsz    Delay2,f            ; The outer loop takes and additional 3 instructions per lap * 256 loops
     goto      A2DDelayLoop        ; (768+3) * 256 = 197376 instructions / 1M instructions per second = 0.197 sec.
                                   ; call it two-tenths of a second.
     movlw     .13                 ; Delay another 10mS plus whatever was above
     movwf     Delay2

; 10ms delay
TenmSdelay:     
     decfsz    Delay1,f
     goto      TenmSdelay
     decfsz    Delay2,f
     goto      TenmSdelay
     
; rotate the LED across the LEDs
Rotate:
     bcf       STATUS, C           ; Ensure we don't rotate a 1 from the carry into bit 7.
     rrf       Display,f
     btfsc     STATUS,C            ; Did the bit rotate into the carry?
     bsf       Display,7           ; yes, put it into bit 7.
     goto      MainLoop

; debounce and process switch press
Debounce:
	nop                            ; wait for switch debounce
	nop
	btfsc PORTB, 0				   ; check that the swtich is still pressed
	return  					   ; if not, return
	btfsc ButtonHeld, 0			   ; check that switch was not held down
	return						   ; if yes, return
	movfw PORTD					   ; move LED display to working reg
	xorlw 0x08					   ; check if LED3 is lit
	btfsc STATUS, Z				    
	goto Caught					   ; if yes, goto Caught
	return						   ; else, return

; hold LED until switch is released
Caught:
	btfss PORTB, 0				   ; while switch is held, stay in loop
	goto $-1
	return  					   ; once switch is released, return		

    end
     
